package com.masiyi.minio.template;


import com.masiyi.minio.config.MinIOProperties;
import com.masiyi.minio.dto.Fileinfo;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * @author masiyi
 */
public class MinIOTemplate {

    private static final Logger log = LoggerFactory.getLogger(MinIOTemplate.class);

    private MinioClient minioClient;
    private MinIOProperties minIOProperties;

    public MinIOTemplate(MinioClient minioClient, MinIOProperties minIOProperties) {
        this.minioClient = minioClient;
        this.minIOProperties = minIOProperties;
    }

    public MinioClient getMinioClient() {
        return minioClient;
    }

    /**
     * 创建一个桶
     */
    public void createBucket(String bucket) {
        try {
            boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
            if (!found) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 上传一个文件
     */
    public void uploadFile(InputStream stream, String bucket, String objectName) {
        try {
            minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(objectName)
                    .stream(stream, -1, 10485760).build());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 列出所有的桶
     */
    public List<String> listBuckets() {
        try {
            List<Bucket> list = minioClient.listBuckets();
            List<String> names = new ArrayList<>();
            list.forEach(b -> {
                names.add(b.name());
            });
            return names;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return Collections.emptyList();
    }

    /**
     * 列出一个桶中的所有文件和目录
     */
    public List<Fileinfo> listFiles(String bucket) {
        Iterable<Result<Item>> results = minioClient.listObjects(
                ListObjectsArgs.builder().bucket(bucket).recursive(true).build());

        List<Fileinfo> infos = new ArrayList<>();
        results.forEach(r -> {
            Fileinfo info = new Fileinfo();
            try {
                Item item = r.get();
                info.setFilename(item.objectName());
                info.setDirectory(item.isDir());
                infos.add(info);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        return infos;
    }

    /**
     * 下载一个文件
     */
    public InputStream download(String bucket, String objectName) {
        try {
            InputStream stream = minioClient.getObject(
                    GetObjectArgs.builder().bucket(bucket).object(objectName).build());
            return stream;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 删除一个桶
     */
    public void deleteBucket(String bucket) {
        try {
            minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucket).build());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 删除一个对象
     */
    public void deleteObject(String bucket, String objectName) {
        try {
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(objectName).build());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }


    /**
     * 复制文件
     */
    public void copyObject(String sourceBucket, String sourceObject, String targetBucket, String targetObject) {
        try {
            this.createBucket(targetBucket);
            minioClient.copyObject(CopyObjectArgs.builder().bucket(targetBucket).object(targetObject)
                    .source(CopySource.builder().bucket(sourceBucket).object(sourceObject).build()).build());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 获取文件信息
     */
    public String getObjectInfo(String bucket, String objectName) {
        try {
            return minioClient.statObject(StatObjectArgs.builder().bucket(bucket).object(objectName).build()).toString();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 生成一个给HTTP GET请求用的presigned URL。浏览器/移动端的客户端可以用这个URL进行下载，即使其所在的存储桶是私有的。
     */
    public String getPresignedObjectUrl(String bucketName, String objectName, Integer expires) {
        try {
            GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs
                    .builder().bucket(bucketName).object(objectName).expiry(expires).method(Method.GET).build();
            return minioClient.getPresignedObjectUrl(build);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取minio中所有的文件
     */
    public List<Fileinfo> listAllFile() {
        List<String> list = this.listBuckets();
        List<Fileinfo> fileinfos = new ArrayList<>();
        for (String bucketName : list) {
            fileinfos.addAll(this.listFiles(bucketName));
        }
        return fileinfos;
    }


}
